/**
 * 
 */
package vue.globalBar;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

import model.session.ExecutableSessionBlock;
import vue.popup.IJPopupMenu;
import vue.popup.JPopupExecution;
import vue.session.IGExecutionBlock;
import controller.ISessionManager;

/**
 * A representation of a solver/preprocessor running for the GlobalBar. It is somehow associate to
 * {@link ExecutableSessionBlock}.
 * 
 * @author GRONOWSKI Stephane svan001@aol.com
 * 
 *         igsat 2010
 * 
 */
public class IGBarExecution extends IGGlobalBarItem implements MouseListener, ActionListener {
	private static final long	serialVersionUID		= 1L;

	public static final String	TIME_PREFIX				= "Time: ";
	public static final String	TOTAL_TIME_PREFIX		= "Total: ";
	public static final String	MEMORY_PREFIX			= "Mem: ";
	public static final String	STATE_PREFIX			= "State: ";


	public static final String	DEFAULT_DESCRIPTION		= "Execution";
	public static final String	UNKNOW					= "UNKNOW";

	public static final int		DESCRIPTION_FONT_SIZE	= 11;
	public static final int		TIME_MEMORY_FONT_SIZE	= 10;
	public static final int		HEIGHT					= 45;


	protected JLabel			description				= new JLabel(DEFAULT_DESCRIPTION, JLabel.CENTER);
	protected JLabel			state					= new JLabel(STATE_PREFIX + UNKNOW, JLabel.CENTER);
	protected JLabel			time					= new JLabel(TIME_PREFIX + UNKNOW, JLabel.LEFT);
	protected JLabel			totalTime				= new JLabel(TIME_PREFIX + UNKNOW, JLabel.LEFT);
	protected JLabel			memory					= new JLabel(MEMORY_PREFIX + UNKNOW, JLabel.LEFT);
	protected IJPopupMenu		rightMenu;

	protected Timer				timer					= new Timer(1000, this);
	protected long				runningTime				= 0;

	protected IGExecutionBlock	exec					= null;

	/**
	 * Create an {@link IGBarExecution}.
	 * 
	 * @param exec
	 *            the {@link IGExecutionBlock} associate
	 * @param manager
	 *            the session manager
	 */
	public IGBarExecution(IGExecutionBlock exec, ISessionManager manager) {
		this.exec = exec;

		// setLayout(new GridLayout(1, 2));
		setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

		if (exec != null)
		{
			description.setText(exec.getExec().getDescritpion());
			state.setText(exec.getExec().getStatus().name());
			time.setText(TIME_PREFIX + UNKNOW);
			totalTime.setText(TOTAL_TIME_PREFIX + exec.getExec().getHumanTotalExecutionTime());

			memory.setText(MEMORY_PREFIX + UNKNOW);
		}

		JPanel panel = new JPanel(new GridLayout(2, 1));
		panel.add(description);
		// description.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		description.setFont(new Font(Font.MONOSPACED, Font.PLAIN, DESCRIPTION_FONT_SIZE));
		panel.add(state);
		// state.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		// panel.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.BLACK));
		add(panel);

		panel = new JPanel(new GridLayout(3, 1));
		panel.add(time);
		// time.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		time.setFont(new Font(Font.MONOSPACED, Font.PLAIN, TIME_MEMORY_FONT_SIZE));
		panel.add(totalTime);
		// totalTime.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		totalTime.setFont(new Font(Font.MONOSPACED, Font.PLAIN, TIME_MEMORY_FONT_SIZE));
		panel.add(memory);
		// memory.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		memory.setFont(new Font(Font.MONOSPACED, Font.PLAIN, TIME_MEMORY_FONT_SIZE));
		panel.setBorder(BorderFactory.createMatteBorder(1, 4, 1, 2, getBackground()));

		add(panel);

		rightMenu = new JPopupExecution(exec, manager);

		setBorder(BorderFactory.createLineBorder(Color.BLACK));
		// setSize(getPreferredSize());
		Dimension dim = getMaximumSize();
		dim.setSize(dim.width, HEIGHT);
		setMaximumSize(dim);

		addMouseListener(this);
	}

	/**
	 * refresh the informations.
	 */
	public void refresh() {
		if (exec != null)
		{
			description.setText(exec.getExec().getDescritpion());
			state.setText(exec.getExec().getStatus().name());

			time.setText(TIME_PREFIX + UNKNOW);
			totalTime.setText(TOTAL_TIME_PREFIX + exec.getExec().getHumanTotalExecutionTime());

			memory.setText(MEMORY_PREFIX + UNKNOW);

			// refresh pop up menu
			rightMenu.refresh();
			Dimension dim = getMaximumSize();
			dim.setSize(dim.width, HEIGHT);
			setMaximumSize(dim);
		}
	}


	/**
	 * Return the {@link IGExecutionBlock} associate.
	 * 
	 * @return the {@link IGExecutionBlock} associate.
	 */
	public IGExecutionBlock getExec() {
		return exec;
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		exec.notifySelected();
	}


	@Override
	public void mouseEntered(MouseEvent e) {
	}


	@Override
	public void mouseExited(MouseEvent e) {
	}


	@Override
	public void mousePressed(MouseEvent e) {
		if (e.isPopupTrigger())
			rightMenu.show(e.getComponent(), e.getX(), e.getY());
	}


	@Override
	public void mouseReleased(MouseEvent e) {
		if (e.isPopupTrigger())
			rightMenu.show(e.getComponent(), e.getX(), e.getY());
	}

	public void startTimer() {
		runningTime = 0;
		timer.start();
	}

	public void stopTimer() {
		runningTime = 0;
		timer.stop();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == timer)
		{
			runningTime++;
			time.setText(TIME_PREFIX + getHumanExecutionTime(runningTime));
			return;
		}
	}

	public String getHumanExecutionTime(long time) {

		long h = time / 3600;
		time %= 3600;
		long m = time / 60;
		time %= 60;
		long s = time;

		String res = "";
		if (h != 0)
			res = h + "h";
		if (m != 0)
			res += m + "m ";
		if (s != 0)
			res += s + "s ";
		if (res.isEmpty())
			res = "none";

		return res;
	}
}
